﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO.Ports;

namespace car_o_matic
{
    [Serializable]
    class Worker
    {
        //function & speed code list 
        List<Byte[]> functionList = new List<byte[]>();
        List<Byte[]> speedList = new List<byte[]>();

        //serial port handler
        [NonSerialized]
        SerialPort port = new SerialPort("COM6", 9600, Parity.Odd, 8, StopBits.Two);

        //list with vehicles
        public List<Vehicle> vehicles = new List<Vehicle>();

        //timer for update en redraw
        [NonSerialized]
        Timer updateTimer;
        [NonSerialized]
        Timer drawTimer;
        
        // This method will be called when the thread is started.
        public void DoWork(int period)
        {
            //fill list with bytes (maybe static)
            functionList.Add(new byte[] { 0x60, 0x81 });   //Fahrlicht
            functionList.Add(new byte[] { 0x40, 0x81 });   //Blinker links
            functionList.Add(new byte[] { 0x40, 0x82 });   //Blinker rechts
            functionList.Add(new byte[] { 0x40, 0x83 });   //Warnblinker
            
            //fill speed list
            speedList.Add(new byte[] { 0x40, 0xC8 });   //FS0
            speedList.Add(new byte[] { 0x40, 0xC9 });   //FS1
            speedList.Add(new byte[] { 0x40, 0xCA });   //FS2
            speedList.Add(new byte[] { 0x40, 0xCB });   //FS3
            speedList.Add(new byte[] { 0x40, 0xCC });   //FS4
            speedList.Add(new byte[] { 0x40, 0xCD });   //FS5
            speedList.Add(new byte[] { 0x40, 0xCE });   //FS6
            speedList.Add(new byte[] { 0x40, 0xCF });   //FS7
            speedList.Add(new byte[] { 0x40, 0xD8 });   //FS8
            speedList.Add(new byte[] { 0x40, 0xD9 });   //FS9
            speedList.Add(new byte[] { 0x40, 0xDA });   //FS10
            speedList.Add(new byte[] { 0x40, 0xDB });   //FS11
            speedList.Add(new byte[] { 0x40, 0xDC });   //FS12
            speedList.Add(new byte[] { 0x40, 0xDD });   //FS13
            speedList.Add(new byte[] { 0x40, 0xDE });   //FS14
            speedList.Add(new byte[] { 0x40, 0xDF });   //FS15
            speedList.Add(new byte[] { 0x40, 0xE8 });   //FS16
            speedList.Add(new byte[] { 0x40, 0xE9 });   //FS17
            speedList.Add(new byte[] { 0x40, 0xEA });   //FS18
            speedList.Add(new byte[] { 0x40, 0xEB });   //FS19
            speedList.Add(new byte[] { 0x40, 0xEC });   //FS20
            speedList.Add(new byte[] { 0x40, 0xED });   //FS21
            speedList.Add(new byte[] { 0x40, 0xEE });   //FS22
            speedList.Add(new byte[] { 0x40, 0xEF });   //FS23
            speedList.Add(new byte[] { 0x40, 0xF8 });   //FS24
            speedList.Add(new byte[] { 0x40, 0xF9 });   //FS25
            speedList.Add(new byte[] { 0x40, 0xFA });   //FS26
            speedList.Add(new byte[] { 0x40, 0xFB });   //FS27
            speedList.Add(new byte[] { 0x40, 0xFC });   //FS28
            speedList.Add(new byte[] { 0x40, 0xFD });   //FS29
            speedList.Add(new byte[] { 0x40, 0xFE });   //FS30
            speedList.Add(new byte[] { 0x40, 0xFF });   //FS31

            //open serialport
            port.Open();

            updateTimer = new Timer(new TimerCallback(update), null, 1000, period);
            drawTimer = new Timer(new TimerCallback(draw), null, 1000, period);

            Console.WriteLine("worker thread: working...");
        }

        //method used to kill the thread
        public void RequestStop()
        {
            updateTimer.Dispose();
            drawTimer.Dispose();

            //close serial port
            port.Close();
        }

        //updates vehicle positions, settings and send data to car
        public void update(object callback)
        {
            //Console.WriteLine("worker thread: running update");
            foreach (Vehicle tmpVehicle in vehicles)
            {
                
                //send the data out the door
         
                   if (tmpVehicle.needsTX)
                   {
                       if (tmpVehicle.stop)
                       {
                           port.Write(new byte[] { Byte.Parse(tmpVehicle.address.ToString()), 0x40, 0xC0 }, 0, 3);
                           tmpVehicle.stop = false;
                       }
                       //headlights
                       if (tmpVehicle.functions[0])
                       {
                           port.Write(new byte[] { Byte.Parse(tmpVehicle.address.ToString()), functionList[0][0], functionList[0][1] }, 0, 3);
                       }
                       else
                       {
                           port.Write(new byte[] { Byte.Parse(tmpVehicle.address.ToString()), functionList[0][0], 0x80 }, 0, 3);
                       }

                            //warning lights
                            if (tmpVehicle.functions[1] && tmpVehicle.functions[2])
                            {
                                port.Write(new byte[] { Byte.Parse(tmpVehicle.address.ToString()), functionList[3][0], functionList[3][1] }, 0, 3);
                            }
                            //indicators left
                            else if (tmpVehicle.functions[1])
                            {
                                port.Write(new byte[] { Byte.Parse(tmpVehicle.address.ToString()), functionList[1][0], functionList[1][1] }, 0, 3);
                            }
                            //indicators right
                            else if (tmpVehicle.functions[2])
                            {
                                port.Write(new byte[] { Byte.Parse(tmpVehicle.address.ToString()), functionList[2][0], functionList[2][1] }, 0, 3);
                            }
                            else
                            {
                                port.Write(new byte[] { Byte.Parse(tmpVehicle.address.ToString()), functionList[2][0], 0x80 }, 0, 3);
                            }
                            
                            //speed
                            port.Write(new byte[] { Byte.Parse(tmpVehicle.address.ToString()), speedList[tmpVehicle.speed][0], speedList[tmpVehicle.speed][1] }, 0, 3);
                            
                            tmpVehicle.needsTX = false;
                }

            }
            
        }

        //draws or redraws the map
        public void draw(object callback)
        {
            //Console.WriteLine("worker thread: running draw");
        }

        public void addVehicle(Vehicle tmpVehicle)
        {
            vehicles.Add(tmpVehicle);
        }
    }
}
